package boot

import (
	"chrent.com/ServiceManage/boot/ds"
	"chrent.com/ServiceManage/models"
	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/golang-module/dongle"
	"github.com/pkg/errors"
	"net/http"
	"time"
)

func AuthMiddle() *jwt.GinJWTMiddleware {
	var identityKey = "email"
	authMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
		SendCookie:  true,
		Realm:       "ServiceManage",
		Key:         []byte("sdkfjlskdjcmxvniuqwe871263jdbxmcnv,mnqwye8765dgh165"),
		Timeout:     time.Hour,
		MaxRefresh:  time.Hour,
		IdentityKey: identityKey,
		LoginResponse: func(c *gin.Context, code int, token string, expire time.Time) {
			c.JSON(http.StatusOK, gin.H{
				"code":    http.StatusOK,
				"result":  gin.H{"token": "Bearer " + token, "expire": expire.Format(time.RFC3339)},
				"message": "成功",
			})
		},
		PayloadFunc: func(data interface{}) jwt.MapClaims {
			if v, ok := data.(*models.User); ok {
				return jwt.MapClaims{
					identityKey: v.Email,
					"name":      v.Name,
					"id":        v.Id,
				}
			}
			return jwt.MapClaims{}
		},
		IdentityHandler: func(c *gin.Context) interface{} {
			claims := jwt.ExtractClaims(c)
			return &models.User{
				Email: claims[identityKey].(string),
				Name:  claims["name"].(string),
				Id:    uint(claims["id"].(float64)),
			}
		},
		Authenticator: func(c *gin.Context) (interface{}, error) {
			loginVals := models.User{}
			if err := c.ShouldBindWith(&loginVals, binding.JSON); err != nil {
				return "", jwt.ErrMissingLoginValues
			}
			useremail := loginVals.Email
			password := loginVals.Password
			user := models.User{}
			if err := ds.Db().Where("email=?", useremail).First(&user).Error; err != nil {
				return nil, errors.New("用户不存在")
			}
			if dongle.Verify.FromRawString(user.Password, password).ByBcrypt().ToBool() {
				return &user, nil
			}

			return nil, jwt.ErrFailedAuthentication
		},
		Authorizator: func(data interface{}, c *gin.Context) bool {
			if v, ok := data.(*models.User); ok && v.Email != "" {
				c.Set(models.UserKey, v)
				return true
			}

			return false
		},
		Unauthorized: func(c *gin.Context, code int, message string) {
			c.JSON(code, gin.H{
				"code":    403,
				"message": message,
			})
		},
		// TokenLookup is a string in the form of "<source>:<name>" that is used
		// to extract token from the request.
		// Optional. Default value "header:Authorization".
		// Possible values:
		// - "header:<name>"
		// - "query:<name>"
		// - "cookie:<name>"
		// - "param:<name>"
		TokenLookup: "header: Authorization, query: token, cookie: jwt",
		// TokenLookup: "query:token",
		// TokenLookup: "cookie:token",

		// TokenHeadName is a string in the header. Default value is "Bearer"
		TokenHeadName: "Bearer",

		// TimeFunc provides the current time. You can override it to use another time value. This is useful for testing or if your server uses a different time zone than your tokens.
		TimeFunc: time.Now,
	})
	if err != nil {
		panic(err)
	}
	err = authMiddleware.MiddlewareInit()
	if err != nil {
		panic(err)
	}
	return authMiddleware
}
func NewCors() gin.HandlerFunc {
	return cors.New(cors.Config{
		AllowAllOrigins: true,
		//AllowOrigins:           []string{"*"},
		AllowMethods:           []string{"*"},
		AllowHeaders:           []string{"*"},
		AllowCredentials:       false,
		ExposeHeaders:          []string{"*"},
		MaxAge:                 0,
		AllowWildcard:          true,
		AllowBrowserExtensions: true,
		AllowWebSockets:        true,
		AllowFiles:             true,
	})
}
